// Copyright (c) 2023 Presto Labs Pte. Ltd.
// Author: tianqiang

#pragma once

#include <list>
#include <memory>
#include <string>
#include <unordered_map>

#include "coin2/exchange/base/order/order.h"
#include "coin2/exchange/mexc/api_util_v3/auth_key.h"
#include "coin2/exchange/mexc/api_util_v3/rate_tracker.h"
#include "coin2/exchange/mexc/symbology_v3/product.h"
#include "coin2/exchange/order/mexc.pb.h"

namespace coin2::exchange::mexc::api_order_v3 {

enum MexcOrderSubTopicId : int {
  REST_DEPOSIT = 10000,
  REST_WITHDRAWAL = 10001,
  DEPOSIT_SUBACCOUNT = 10002,
  WITHDRAW_SUBACCOUNT = 10003
};

class MexcNativePrivateClient : public coin2::exchange::base::order::NativePrivateClient {
 public:
  using RestParams = coin2::exchange::order::MexcRestParams;
  using NativeClientConfig = coin2::exchange::order::OrderConnectionConfig;
  using HttpContextPtr = std::shared_ptr<AsioHttpContext>;
  using ActionType = coin2::exchange::base::order::NativePrivateClient::ActionType;
  using MexcRateTracker = coin2::exchange::mexc::api_util_v3::MexcRateTracker;
  using MexcProduct = coin2::exchange::mexc::symbology_v3::MexcProduct;
  using MexcRestAuth = coin2::exchange::mexc::api_util_v3::MexcRestAuth;
  using AsioHttpContextList = std::list<std::shared_ptr<AsioHttpContext>>;

 public:
  explicit MexcNativePrivateClient(const MarketExchangeApi& mea, const NativeClientConfig& config);

  HttpContextPtr QueryAccountBalance();
  HttpContextPtr QueryOpenOrders(const RestParams& params);
  HttpContextPtr QueryAllOrders(const RestParams& params);
  HttpContextPtr QueryFillOrders(const RestParams& params);
  // HttpContextPtr QueryOrdersByIds(const RestParams& params);

  HttpContextPtr PlaceSingleOrder(const RestParams& params);
  HttpContextPtr PlaceBatchOrders(const std::vector<RestParams>& params);
  HttpContextPtr CancelOrder(const RestParams& params);
  HttpContextPtr PlaceOrderNorm(const OrderExecution&) override;
  HttpContextPtr CancelOrderNorm(const OrderExecution&) override;

  RestParams GetRestOrderParams(const OrderSpec& order_spec, int64_t proc_order_id);
  RestParams GetRestCancelParams(const IOrderContext& order_context);

  HttpContextPtr QueryDeposit(const RestParams& params);
  HttpContextPtr QueryWithdrawal(const RestParams& params);
  HttpContextPtr QueryTransfer(const RestParams& params);

  HttpContextPtr GenListenKey(bool is_init);
  HttpContextPtr ExtendListenKey();

  void Prepare();
  std::string DebugString() const;
  AsioHttpContextList SubmitRestQueryList(const RestQueryProto& query);

 private:
  int64_t start_time_;
  std::string listen_key_;
  std::unordered_map<std::string, int32_t> api_block_info_;
  std::unordered_map<std::string, int32_t> api_req_info_;

 private:
  MexcRateTracker* local_rate_tracker_;
};

}  // namespace coin2::exchange::mexc::api_order_v3
